package pr2.mutacion;

import java.util.ArrayList;

import pr2.cromosoma.Cromosoma;
import pr2.cromosoma.CromosomaPVC;
import pr2.cromosoma.Distancias;

public class MutacionHeuristicaDist implements
		EstrategiaMutacion<CromosomaPVC> {

	private int numMutaciones;

	public MutacionHeuristicaDist(int numMutaciones) {
		this.numMutaciones = numMutaciones;
	}

	@Override
	public void muta(CromosomaPVC cromosoma, double prob) {

		double probabilidad = Math.random();
		ArrayList<Integer> posCiudades, ciudades;
		ArrayList<String> perms;
		double punt, mejorPunt = Double.MAX_VALUE;
		Cromosoma<CromosomaPVC> cromosomaAux;

		if (probabilidad <= prob) {

			posCiudades = new ArrayList<Integer>();
			ciudades = new ArrayList<Integer>();

			// Calculo las ciudades a permutar teniendo en cuenta las mas lejanas entre sí
			for (int i = 0; i < numMutaciones; i++) {
				double maxDistancia = Double.MIN_VALUE;
				Integer candidatoMutar = 0;
				for (int j = 1; j < cromosoma.getFenotipo().size(); j++) {
					double dist = Distancias.getDist(cromosoma.getFenotipo()
							.get(j), cromosoma.getFenotipo().get(j - 1));
					if ((dist > maxDistancia) && !(posCiudades.contains(j))) {
						candidatoMutar = j;
						maxDistancia = dist;
					}
				}
				posCiudades.add(candidatoMutar);
				ciudades.add(cromosoma.getFenotipo().get(candidatoMutar));
		
			}

			perms = new ArrayList<String>();

			// Calculo las posibles permutaciones
			calculaPermutaciones(perms, "", ciudades);

			cromosomaAux = cromosoma.clone();

			for (String perm : perms) {
				String[] permutacion = perm.split(";");

				for (int i = 0; i < numMutaciones; i++) {
					cromosomaAux.getFenotipo().set(posCiudades.get(i),
							Integer.parseInt(permutacion[i]));
				}

				punt = cromosomaAux.evalua();

				// Me quedo con la mejor permutacion
				if (punt < mejorPunt) {
					mejorPunt = punt;
					for (int i = 0; i < cromosoma.getFenotipo().size(); i++)
						cromosoma.getFenotipo().set(i,
								cromosomaAux.getFenotipo().get(i));
				}
			}

		}

	}

	private void calculaPermutaciones(ArrayList<String> perms, String tupla,
			ArrayList<Integer> conjunto) {
		if (conjunto.size() == 1) {
			tupla += ";" + conjunto.get(0).toString();
			perms.add(tupla);
			tupla = "";
		}
		for (int i = 0; i < conjunto.size(); i++) {
			Integer b = conjunto.remove(i);
			calculaPermutaciones(perms, (tupla.equals("") ? b.toString()
					: tupla + ";" + b), conjunto);
			conjunto.add(i, b);
		}
	}

}
